package com.gitee.jmash.rbac.shiro.authz;

import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import com.gitee.jmash.common.security.DefaultJmashPrincipal;
import com.gitee.jmash.common.security.JmashPrincipal;
import com.gitee.jmash.rbac.client.shiro.JmashJsonWebToken;
import com.gitee.jmash.rbac.client.shiro.JmashSimpleByteSource;
import com.gitee.jmash.rbac.client.shiro.authc.JmashShiroJwtToken;
import com.gitee.jmash.rbac.client.shiro.authc.JmashShiroToken;
import com.gitee.jmash.rbac.client.shiro.authz.JmashBaseAuthorizingRealm;
import com.gitee.jmash.rbac.client.shiro.authz.JmashJWTParser;
import com.gitee.jmash.rbac.utils.AuthzUtil;
import jakarta.enterprise.inject.spi.CDI;
import jmash.rbac.protobuf.RolePermSet;

/**
 * Shiro UCenter 登录
 * 
 * @author cgd
 *
 */
public class JmashAuthorizingRealm extends JmashBaseAuthorizingRealm {

  private Log log = LogFactory.getLog(JmashAuthorizingRealm.class);

  public JmashJWTParser getJWTParser() {
    return CDI.current().select(JmashJWTParser.class).get();
  }

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
    JmashJsonWebToken token = (JmashJsonWebToken) arg0.getPrimaryPrincipal();
    JmashPrincipal principal = DefaultJmashPrincipal.create(token);
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    String tenant = token.getIssuer();
    try {
      RolePermSet rolePermSet = AuthzUtil.userRolesPerms(tenant, principal);
      info.setRoles(rolePermSet.getRoleCodesList().stream().collect(Collectors.toSet()));
      info.setStringPermissions(
          rolePermSet.getPermCodesList().stream().collect(Collectors.toSet()));
    } catch (Exception ex) {
      log.error("Get User Role and Perm ERROR:", ex);
      throw new AuthorizationException(ex);
    }
    return info;
  }

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0)
      throws AuthenticationException {
    if (arg0 instanceof JmashShiroJwtToken) {
      try {
        // 1 JmashJwtToken
        JmashShiroJwtToken token = (JmashShiroJwtToken) arg0;
        JmashJsonWebToken jsonWebToken = getJWTParser().parse(token.getAuthorization());
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(jsonWebToken, null,
            new JmashSimpleByteSource(), this.getName());
        return info;
      } catch (Exception ex) {
        log.error("JWT ERROR:", ex);
        throw new AuthenticationException(ex);
      }
    }
    return null;
  }

  @Override
  public boolean supports(AuthenticationToken token) {
    return (token instanceof JmashShiroJwtToken) || (token instanceof JmashShiroToken);
  }

}
